package edu.buaa.common.client;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import edu.buaa.common.utils.PVal;
import edu.buaa.utils.Triple;

import java.sql.*;
import java.util.List;

public abstract class PostgreSqlExecutorClient extends AbstractSQLClient {
    private final String user = "postgres";
    private final String password = "langduhua";

    public PostgreSqlExecutorClient(String serverHost, String dbName, int parallelCnt) throws Exception {
        super(serverHost, dbName, parallelCnt);
    }

    @Override
    protected void createDbIfNotExist(String serverHost, String dbName) throws SQLException, ClassNotFoundException {
        Class.forName("org.postgresql.Driver");
        try (Connection conn = DriverManager.getConnection("jdbc:postgresql://" + serverHost + ":5432/", user, password);
             Statement stmt = conn.createStatement()) {
            conn.setAutoCommit(true);
            ResultSet rs = stmt.executeQuery("select database.datname from pg_catalog.pg_database database where database.datname = '"+dbName+"'");
            if (!rs.next()) stmt.execute("CREATE database "+dbName);
        }
    }

    @Override
    protected Connection createNormalConnection(String serverHost, String dbName) throws SQLException {
        return DriverManager.getConnection("jdbc:postgresql://" + serverHost + ":5432/"+dbName, user, password);
    }

    @Override
    protected void connected(Connection conn) throws Exception {
        conn.setAutoCommit(true);
        try (Statement stmt = conn.createStatement()) {
            for(String q : createTables()){
                stmt.execute(q);
            }
        }
    }

    @Override
    public String currentStorageStatus() throws InterruptedException, SQLException {
        String sql = "select t.relname as relname,pg_relation_size(t.relid) as tablesize," +
                "pg_relation_size(i.indexrelid) as indexsize from " +
                "pg_stat_user_tables as t left join pg_stat_user_indexes as i on t.relid=i.relid";
        Connection conn = connectionPool.take();
        JSONArray arr = new JSONArray();
        try(Statement stmt = conn.createStatement()) {
            conn.setAutoCommit(true);
            ResultSet rs = stmt.executeQuery(sql);
            while(rs.next()) {
                JSONObject obj = new JSONObject();
                obj.put("relname", rs.getString("relname"));
                obj.put("tablesize", rs.getLong("tablesize"));
                obj.put("indexsize", rs.getLong("indexsize"));
                arr.add(obj);
            }
        }
        connectionPool.put(conn);
        return arr.toJSONString();
    }
    protected String createTable(String name, List<Triple<String, PVal.Type, Integer>> props){
        StringBuilder sb = new StringBuilder("CREATE TABLE IF NOT EXIST ").append(name).append("(id char(16) PRIMARY KEY");
        for(Triple<String, PVal.Type, Integer> t : props){
            sb.append(t.getLeft()).append(' ');
            switch (t.getMiddle()){
                case INT:
                    sb.append("INTEGER, ");
                    break;
                case FLOAT:
                    sb.append("FLOAT, ");
                    break;
                case STRING:
                    sb.append("CHAR(16), ");
            }
        }
        sb.setCharAt(sb.length()-1, ' ');
        sb.append(')');
        return sb.toString();
    }
}
